package com.wf.chatManagement.service.local.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.wf.apicommons.config.RabbitConstant;
import com.wf.apicommons.entity.MessageBoard.LeavingAMessage;
import com.wf.apicommons.entity.MessageBoard.MqMessage;
import com.wf.apicommons.entity.chatManagement.ChatRecord;
import com.wf.apicommons.utils.JWTUtils;
import com.wf.apicommons.utils.RedisUtils;
import com.wf.apicommons.utils.SnowflakeUtil;
import com.wf.chatManagement.service.local.ChatRelatedService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * @Description: 推送消息
 */
@Service
@Slf4j
public class PushMessageService {
    /**
     * 当前在线用户key
     */
    public static final String ONLINE_USERS = "online_users_map_key";

    /**
     * 群聊和对应的用户关系key
     */
    public static final String GROUP_USER_KEY = "group_user_key";


    /**
     * 离线用户留言数据key
     */
    public static final String OFFLINE_USER_MESSAGE = "offline_user_message";


    /**
     * 离线用户聊天数据key
     */
    public static final String OFFLINE_USER_CHAT = "offline_user_chat";

    /**
     * 消息类型-聊天
     */
    public static final int MESSAGE_TYPE_CHAT = 0;

    /**
     * 消息类型-留言
     */
    public static final int MESSAGE_TYPE_LEAVING_A_MESSAGE = 1;


    @Resource
    private RedisUtils redisUtils;

    @Resource
    private WebSocketService webSocketService;

    @Autowired
    @Qualifier("chatRelatedServiceImpl")
    private ChatRelatedService chatRelatedService;

    /**
     * 新增在线用户
     *
     * @param userId 用户ID
     * @return
     */
    public boolean newOnlineUsers(String userId) {
        //存储当前在线用户
        return redisUtils.hSet(ONLINE_USERS, userId, "1");
    }

    /**
     * 减少在线用户
     *
     * @param userId 用户ID
     * @return
     */
    public void reduceOnlineUsers(String userId) {
        //删除在线状态
        redisUtils.hDel(ONLINE_USERS, userId);
    }

    /**
     * 发送聊天消息
     *
     * @param messageContent                      消息内容
     * @param isCachedMessage                     当前发送的是否为离线缓存消息
     * @param isTheGroupChatInitializationMessage 是否为群聊初始化消息
     * @return
     */
    public boolean sendChatMessage(String messageContent, boolean isCachedMessage, boolean isTheGroupChatInitializationMessage) {
        try {
            MqMessage<ChatRecord> mqMessage = JSONUtil.toBean(messageContent, MqMessage.class);
            ChatRecord chatRecord = JSONUtil.toBean(mqMessage.getJsonData(), ChatRecord.class);

            if (chatRecord != null && StrUtil.isNotBlank(chatRecord.getSenderId().getID()) && StrUtil.isNotBlank(chatRecord.getMessageContent()) && StrUtil.isNotBlank(chatRecord.getRecipientId())) {
                if (!isCachedMessage) {
                    //设置发送时间与读取状态
                    chatRecord.setID(SnowflakeUtil.getID());
                    chatRecord.setSendTime(new Date());

                    //添加一条聊天记录
                    chatRelatedService.addNewChatRecord(chatRecord);
                    //重新转化消息
                    mqMessage.setJsonData(JSONUtil.toJsonStr(chatRecord));
                    messageContent = JSONUtil.toJsonStr(mqMessage);
                }

                //判断当前是否为私聊
                if (0 == chatRecord.getType()) {
                    //向指定用户发送信息
                    return webSocketService.sendAssignmentMessage(chatRecord.getRecipientId(), messageContent, MESSAGE_TYPE_CHAT);
                } else if (1 == chatRecord.getType()) {
                    //存储的用户ID
                    Set<String> userIdList = getUserGroupRelationship(chatRecord.getRecipientId());
                    //修改未读数量的参数
                    Map<String, Object> updateParam = new HashMap<String, Object>(3);

                    for (String userId : userIdList) {
                        //避免给当前消息的发送者再次发送,除非是初始化的群聊消息
                        if (!userId.equals(chatRecord.getSenderId().getID()) || isTheGroupChatInitializationMessage) {
                            //填充修改未读数量的参数
                            updateParam.put("operation", 1);
                            updateParam.put("userInformationId", userId);
                            updateParam.put("groupInfoId", chatRecord.getRecipientId());

                            //修改群聊消息未读数量
                            chatRelatedService.updateUnreadNumberOfGroupChatMessages(updateParam);
                            //向指定用户发送信息
                            webSocketService.sendAssignmentMessage(userId, messageContent, MESSAGE_TYPE_CHAT);
                        }

                    }

                }

            }
        } catch (Exception e) {
            log.info("发送聊天消息失败，出现错误：{}", e.getMessage());
        }
        return false;
    }

    /**
     * 缓存当前加入群聊的用户与群的映射关系
     *
     * @param userId
     * @param groupInfoId
     * @return
     */
    public boolean setUserGroupRelationship(String userId, String groupInfoId) {
        Set<String> oldUserList = getUserGroupRelationship(groupInfoId);
        if (oldUserList == null) {
            Set<String> newUserList = new HashSet<>();
            newUserList.add(userId);
            return redisUtils.hSet(GROUP_USER_KEY, groupInfoId, newUserList);
        } else {
            oldUserList.add(userId);
            return redisUtils.hSet(GROUP_USER_KEY, groupInfoId, oldUserList);
        }
    }

    /**
     * 获取当前加入当前群聊的用户列表
     *
     * @param groupInfoId
     * @return
     */
    public Set<String> getUserGroupRelationship(String groupInfoId) {
        return (Set<String>) redisUtils.hGet(GROUP_USER_KEY, groupInfoId);
    }

    /**
     * 监听推送的留言数据
     *
     * @param message
     */
    @RabbitListener(queues = RabbitConstant.LEAVING_A_MESSAGE_QUEUE)
    public void process(String message) {
        sendLeavingAMessage(message);
    }

    /**
     * 发送留言消息
     *
     * @param message
     * @return
     */
    public boolean sendLeavingAMessage(String message) {
        try {
            //获取留言数据
            MqMessage<LeavingAMessage> mqMessage = JSONUtil.toBean(message, MqMessage.class);
            LeavingAMessage leavingAMessage = JSONUtil.toBean(mqMessage.getJsonData(), LeavingAMessage.class);
            if (leavingAMessage != null) {
                //推送留言
                return webSocketService.sendAssignmentMessage(leavingAMessage.getRecipientId().getID(), message, MESSAGE_TYPE_LEAVING_A_MESSAGE);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("发送留言消息出现错误：{}", e.getMessage());
        }
        return false;
    }

    /**
     * 缓存离线聊天消息，当用户不在线时，先将消息存入redis
     *
     * @param message
     * @return
     */
    public boolean setOfflineUserChat(String userId, String message) {
        Set<String> oldOfflineUserChat = getOfflineUserChat(userId);
        if (oldOfflineUserChat == null) {
            Set<String> newOfflineUserChat = new HashSet<>();
            newOfflineUserChat.add(message);
            return redisUtils.hSet(userId, OFFLINE_USER_CHAT, newOfflineUserChat);
        } else {
            oldOfflineUserChat.add(message);
            return redisUtils.hSet(userId, OFFLINE_USER_CHAT, oldOfflineUserChat);
        }
    }

    /**
     * 获取离线缓存的聊天消息
     *
     * @param userId
     * @return
     */
    public Set<String> getOfflineUserChat(String userId) {
        return (Set<String>) redisUtils.hGet(userId, OFFLINE_USER_CHAT);

    }


    /**
     * 缓存离线留言消息，当用户不在线时，先将消息存入redis
     *
     * @param message
     * @return
     */
    public boolean setOfflineUserMessage(String userId, String message) {
        Set<String> oldOfflineUserMessage = getOfflineUserMessage(userId);

        if (oldOfflineUserMessage == null) {
            Set<String> newOfflineUserMessage = new HashSet<>();
            newOfflineUserMessage.add(message);
            return redisUtils.hSet(userId, OFFLINE_USER_MESSAGE, newOfflineUserMessage);
        } else {
            oldOfflineUserMessage.add(message);
            return redisUtils.hSet(userId, OFFLINE_USER_MESSAGE, oldOfflineUserMessage);
        }

    }

    /**
     * 获取离线缓存的留言消息
     *
     * @param userId
     * @return
     */
    public Set<String> getOfflineUserMessage(String userId) {
        return (Set<String>) redisUtils.hGet(userId, OFFLINE_USER_MESSAGE);
    }

    /**
     * 发送缓存的离线消息
     *
     * @param userId
     * @return
     */
    public void sendCachedOfflineMessages(String userId) {

        //获取缓存的聊天消息
        Set<String> offlineUserChat = getOfflineUserChat(userId);
        if (offlineUserChat != null && offlineUserChat.size() > 0) {
            for (String chatMsg : offlineUserChat) {
                sendChatMessage(chatMsg, true, false);
                //清除缓存的消息
                redisUtils.hDel(userId, OFFLINE_USER_CHAT);
            }
        }

        //获取缓存的留言数据
        Set<String> offlineUserMessage = getOfflineUserMessage(userId);
        if (offlineUserMessage != null && offlineUserMessage.size() > 0) {
            for (String leavingAMessage : offlineUserMessage) {
                //清除缓存的留言消息
                redisUtils.hDel(userId, OFFLINE_USER_MESSAGE);
                sendLeavingAMessage(leavingAMessage);
            }
        }
    }


}
